<script setup>
// import { listQuestion } from '@/api/modules/rbac/dcp/large_model_hotspot'
// import { addRecord} from '@/api/modules/rbac/dcp/large_model_questionAnswerRecord'
import Recorder from 'js-audio-recorder';
// import axios from 'axios'
import { fetchEventSource } from '@microsoft/fetch-event-source';
// import { startConversation, textToSpeech } from '@/api/modules/rbac/dcp/large_model_questionAnswerRecord';
// import { useBaseUrl } from './useBaseUrl';
import { getToken } from '@/utils/user';

const state = reactive({
  currentVideoIndex: 0,
  hotTopic: [],
  input: '', // 意见输入框
  list: [], // 存放问答记录
  content: null,
  userId: 1, // 1-用户 2-机器人
  scrollHeight: 'auto', // 内容区域高度
  statusBarHeight: 0, // 状态栏高度
  scrollViewId: '', // 滚动到最底部
  isFocus: false,
  isThinking: true,
  ask: '',
  answer: '',
  isMobile: false, // 是否为手机端
  remenLength: false,
  messageShow: false, // 是否显示反馈成功
  btnShow: true,
  isRecording: false,
  recorder: null,
  // url: import.meta.VITE_APP_API_BASEURL_APP1,
  url: 'http://172.26.7.151:8849/api/sxint-app-digital-comprehensive-platform',
  conversationId: null, // 对话id
  intervalId: null,
  ws: null,
  question: '',
  wakeupFlag: false, // 是否已唤醒
  taskQueue: [], // 定义一个队列用于存储待处理的task_id
  isProcessing: false, // 定义一个变量来标记当前是否有请求正在进行中
  websocketStatus: false, // 开关状态，默认为关闭
  sendAudioInterval: null, // 发送音频流计时器
  answerNum: null, // 总条数
  sleepState: 0, // 0-休眠中 1-已唤醒
  disabled: false, // 休眠中--输入状态，已唤醒--禁用状态
  controller: null,
  answerQueue: [], // 保存接收到的answer队列
  isProcessingAnswer: false, // 是否正在处理
  newMessageReceived: false,
  sendMode: '', // 输入/语音
  index: 0, // 遍历answer计数
  videoKey: null,
  defaultVideoKey: null,
  flag: false, // 是否调用数字人视频
  videos: [
    import('./components/videos/1.mp4'),
    import('./components/videos/1.mp4'),
    import('./components/videos/1.mp4'),
  ],
  changestate: false,
  completeAnswer: '', // 收集回答至40字以上
  remain: [], // 文字转语音集合
  isProcessAudio: false, // 音频是否正在播放
  audio: null, // 得到音频
  isend: false,
  isLengthMoreThanForty: false,
});

// 生命周期钩子：组件挂载时执行
onMounted(() => {
  setItem();
  // 初始化内容高度（
  setScrollHeight();
  // 获取热点问题
  // getHotSpot();
  getConversationId();
  // console.log('已准备好');
  checkMobile();
  window.addEventListener('resize', state.checkMobile);
  // console.log('2');
});

// 计算属性
const videoSrc = computed(() => {
  return state.videos[state.currentVideoIndex];
});

// 初始化websocket
function connectSocketInit() {
  try {
    // const wsurl = state.url.replace("https://", 'wss://') + '/realtimeChat';
    state.ws = new WebSocket('wss://140.246.194.137:1025/prod-api/realtimeChat');
    state.ws.binaryType = 'arraybuffer';
    state.ws.onmessage = websocketOnMessage;
    state.ws.onopen = websocketOnOpen.bind(state);
    state.ws.onerror = websocketOnError;
    state.ws.onclose = websocketClose;
  }
  catch (error) {
    console.error('发生错误：', error);
  }
}
// 连接建立之后的回调
function websocketOnOpen() {
  // console.log("--------连接已建立!---------")
  if (state.ws.readyState === 1) {
    try {
      sendStartFrame();
    }
    catch (error) {
      console.error('发生错误：', error);
    }
  }
}
// 发送开始参数帧
function sendStartFrame() {
  const startFrame = {
    type: 'START',
    data: {
      appid: 85213867,
      appkey: 'mdU63WmBIsWcERhbi57BZ5AB',
      dev_pid: 15372,
      cuid: 'cuid-1',
      format: 'pcm',
      sample: 16000,
    },
  };
  websocketSend(JSON.stringify(startFrame));
  sendAudioFrame();
}
// 发送音频帧
function sendAudioFrame() {
  // 初始化Recorder实例
  state.recorder = new Recorder({
    sampleBits: 16, // 采样位数，支持 8 或 16，默认是16
    sampleRate: 16000, // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，
    numChannels: 1, // 声道，支持 1 或 2， 默认是1
    compiling: true,
  });
  // 获取录音设备
  navigator.mediaDevices.getUserMedia({ audio: true })
    .then(() => { });
  // 开始录音
  state.recorder.start().then(() => {
    state.isRecording = true;
    // console.log('开始录音了=========')
    // 每160ms发送音频流
    state.sendAudioInterval = setInterval(() => {
      // 获取前一次 getNextData() 之后的数据。若没有开启边录边转(compiling为false)，则返回是空数组。
      const pcmBlob = state.recorder.getNextData();
      const combinedArrayBuffer = new ArrayBuffer(pcmBlob.reduce((totalLength, dataView) => totalLength + dataView.byteLength, 0));
      const combinedUint8Array = new Uint8Array(combinedArrayBuffer);
      let offset = 0;
      // dataview格式转二进制音频流
      pcmBlob.forEach((dataView) => {
        const dataViewUint8Array = new Uint8Array(dataView.buffer);
        combinedUint8Array.set(dataViewUint8Array, offset);
        offset += dataView.byteLength;
      });
      websocketSend(combinedArrayBuffer);
    }, 160);
  }).catch((error) => {
    console.error('获取音频流失败:', error);
  });
}
// 发送结束参数帧,断开连接
function sendStopFrame() {
  state.sleepState = 0;
  state.disabled = false;
  state.$message({
    message: '实时语音识别已关闭',
  });
  // 关闭录音
  state.recorder.stop();
  // 关闭播放中的音频
  if (state.audio) {
    state.audio.pause();
    state.audio = null;
  }
  // 释放麦克风资源
  const stream = state.recorder.stream;
  if (stream) {
    const tracks = stream.getTracks();
    tracks.forEach(track => track.stop());
  }
  // 清空计时器，不再发送音频帧给websocket
  clearInterval(state.sendAudioInterval);
  // 发送结束参数帧
  if (state.ws != null) {
    const finishframe = {
      type: 'FINISH',
    };
    websocketSend(JSON.stringify(finishframe));
    // 断开连接
    websocketClose();
  }
}
// 销毁,断开连接
function sendStopFrameDes() {
  state.sleepState = 0;
  state.disabled = false;
  // 关闭录音
  state.recorder.stop();
  // 关闭播放中的音频
  if (state.audio) {
    state.audio.pause();
    state.audio = null;
  }
  // 释放麦克风资源
  const stream = state.recorder.stream;
  if (stream) {
    const tracks = stream.getTracks();
    tracks.forEach(track => track.stop());
  }
  // 清空计时器，不再发送音频帧给websocket
  clearInterval(state.sendAudioInterval);
  // 发送结束参数帧
  if (state.ws != null) {
    const finishframe = {
      type: 'FINISH',
    };
    websocketSend(JSON.stringify(finishframe));
    // 断开连接
    websocketClose();
  }
}
// 处理任务队列
// const processTaskQueue = async () => {
//   // 获取任务队列的长度
//   if (state.isProcessing) {
//     return;
//   }
//   state.isProcessing = true;
//   while (state.taskQueue.length > 0) {
//     const taskId = state.taskQueue.shift();
//     await retryRequest(taskId);
//   }
//   //当任务队列为空时，调用sendAudioFrame方法
//   if (state.taskQueue.length === 0) {
//     sendAudioFrame();
//   }
//   state.isProcessing = false;
// }
// 根据taskid请求音频
// const retryRequest = (taskId) => {
//   return new Promise((resolve, reject) => {
//     axios.get(state.url + '/chat/speechDownload?taskId=' + taskId)
//       .then(res => {
//         if (res.data.data.tasks_info[0].task_status === 'Success') {
//           const audioUrl = res.data.data.tasks_info[0].task_result.speech_url;
//           //存入对应this.list
//           var audio = new Audio(audioUrl);
//           audio.addEventListener('ended', () => {
//             // const totalTasks = this.taskQueue.length;
//             // // 音频结束，继续录音
//             // if (totalTasks == 0) {
//             //    sendAudioFrame();
//             // }
//             resolve(); // 当音频播放结束时调用 resolve 标记任务完成
//           });
//           audio.play();
//         } else {
//           setTimeout(() => {
//             retryRequest(taskId).then(resolve);
//           }, 5000);
//         }
//       }).catch(error => {
//         console.error('请求失败：', error);
//         reject(error);
//       });
//   })
// }
// 数据接收
function websocketOnMessage(event) {
  state.sendMode = 'audio';
  // console.log('event==', event);
  const data = JSON.parse(event.data);
  // const result = data.result;
  const errNo = data.err_no;
  if (errNo === -3101) {
    if (state.recorder) {
      state.recorder.stop();
    }
    state.sleepState = 0;
    // if(state.ws.readyState === 3) {
    connectSocketInit();
    // }
  }
  else {
    // console.log('识别结果:', result);
    switch (data.type) {
      // 唤醒成功
      case 'WAKEUP': {
        state.newMessageReceived = true;
        // 停止文字，发送中断信号
        // if(state.controller) {
        //   state.controller.abort();
        state.answerQueue = [];
        playDefaultVideo();
        state.isProcessingAnswer = false;
        state.isProcessAudio = false;
        // }
        // 停止音频
        // stop();
        state.remain = [];
        if (state.audio) {
          state.audio.pause();
          // state.audio.currentTime = 0; // 重置播放位置
        }
        initScrollBar();
        state.completeAnswer = '';
        state.wakeupFlag = true;
        state.changestate = false;
        state.sleepState = 1;
        state.disabled = true;
        state.$message({
          message: '已唤醒，可以开始提问了',
          type: 'success',
        });
        break;
      }
      case 'QUESTION': {
        state.newMessageReceived = true;
        if (state.wakeupFlag) {
          state.content = data.data.text;
          const text = state.content;
          // 显示用户问题
          send();
          // 显示回答
          getAnswer(text);
        }
        break;
      }
      default:
        // 处理未知类型
        break;
    }
  }
}
// 发送休眠帧
function sendSleepState() {
  state.sleepState = 0;
  state.disabled = false;
  state.wakeupFlag = false;
  state.$message({
    message: '进入休眠状态，需要重新唤醒',
  });
  const sleepFrame = {
    type: 'SLEEP',
    data: {},
  };
  websocketSend(JSON.stringify(sleepFrame));
  // state.test();
}
// 数据发送
function websocketSend(data) {
  // 将音频数据发送到后端
  try {
    state.ws.send(data);
  }
  catch (error) {
    // console.log('出错了', error);
  }
}
// 连接建立失败重连
function websocketOnError(error) {
  console.error('error===', error);
  connectSocketInit();
}
// 关闭
function websocketClose(e) {
  // console.log('断开连接', e);
  if (e && e.code && e.code !== 1000) {
    // 连接已经关闭，重连
    if (state.ws.readyState === 3) {
      connectSocketInit();
    }
  }
}
// 生成对话id
async function getConversationId() {
  await startConversation().then((res) => {
    state.conversationId = res.data.conversation_id;
  }).catch((error) => {
    console.error('请求失败：', error);
  });
}
function getAnswer(text) {
  state.isLengthMoreThanForty = false;
  state.isend = false;
  state.wakeupFlag = false;
  const data = {
    conversationId: state.conversationId,
    text,
  };
  const self = state;

  self.controller = new AbortController();
  const { signal } = self.controller;

  fetchEventSource(`${self.url}/chat/textQueryFlux`, {
    method: 'POST',
    openWhenHidden: true, // 页面退至后台保持连接
    headers: { 'Content-Type': 'application/json', 'Authorization': `${getToken()}` },
    signal,
    body: JSON.stringify(data),
    onmessage(ev) {
      try {
        // debugger
        const eventData = JSON.parse(JSON.parse(ev.data));
        // 换行显示
        if (eventData && eventData.answer !== undefined) {
          eventData.answer = eventData.answer.replace(/\n/g, '<br>');
        }
        self.answerQueue.push(eventData.answer);
        processAnswerQueue();
      }
      catch (err) {
        console.error(err);
        throw err;
      }
    },
  });
  // state.disabled = false
}
async function processAnswerQueue() {
  if (!state.isProcessingAnswer && state.answerQueue.length > 0) {
    state.isProcessingAnswer = true;
    const answer = state.answerQueue.shift();

    if (answer.length === 0) {
      state.isProcessingAnswer = false;
      state.index = 0;
      // 继续处理队列中的 answer
      processAnswerQueue();
    }
    else {
      let leftAnswer = answer;
      if (leftAnswer.includes('<br>')) {
        leftAnswer = leftAnswer.replace(/<br>/g, ''); // 使用正则表达式替换所有的<br>
      }
      const punctuation = ['。', '，', '！', '？', ',', '!', '?', '、']; // 标点符号列表
      const lastObj = state.list[state.list.length - 1];
      for (let i = 0; i < leftAnswer.length; i++) {
        state.completeAnswer += leftAnswer[i];
        if (state.completeAnswer.length > 40 && punctuation.includes(leftAnswer[i])) {
          state.isLengthMoreThanForty = true;
          state.remain.push(state.completeAnswer);
          // 调文字转语音接口
          if (!state.isProcessAudio) {
            getSpeech(state.remain);
          }
          // 继续累加
          state.completeAnswer = leftAnswer.substring(i + 1);
          break; // 提前结束循环
        }
      }
      // lastObj.content += answer;
      // 逐字显示回答
      while (state.index < answer.length) {
        const char = answer[state.index];
        if (char === '<' && answer.substr(state.index, 4) === '<br>') {
          lastObj.content += '<br>';
          state.index += 4; // 跳过<br>符号
        }
        else {
          lastObj.content += char;
          state.index++;
        }
        await new Promise(resolve => setTimeout(resolve, 100)); // 控制逐字显示的速度
      }
      if (state.index === answer.length) {
        state.isProcessingAnswer = false;
        state.index = 0;
        // 继续处理队列中的 answer
        processAnswerQueue();
      }
      // 取消加载
      lastObj.isThinking = false;
      initScrollBar();
    }
  }
  if (state.answerQueue.length === 0 && state.completeAnswer.length > 0 && !state.isend) {
    state.isend = true;
    state.disabled = false;
    state.remain.push(state.completeAnswer);
    state.completeAnswer = '';
    if (!state.isLengthMoreThanForty) {
      getSpeech(state.remain);
    }
  }
  // if (state.answerQueue.length === 0 && state.completeAnswer.length > 0 && state.isend) {
  //   state.disabled = false;
  // }
}
function getSpeech(remain) {
  state.isProcessAudio = true;
  const data = {
    text: remain.shift(),
  };
  const self = state;
  textToSpeech(data).then((res) => {
    const audioUrl = window.URL.createObjectURL(res.data);
    self.audio = document.createElement('audio');
    self.audio.style.display = 'none'; // 防止影响页面布局
    self.audio.controls = true;
    document.body.appendChild(self.audio);
    self.audio.src = audioUrl;
    self.audio.play();
    // 随即调取数字人
    if (!self.changestate) {
      playRandomVideo();
    }
    self.changestate = true;
    // 当前音频播放结束
    self.audio.addEventListener('ended', () => {
      // 存在待播放音频
      if (self.remain.length !== 0) {
        getSpeech(self.remain);
      }
      else {
        self.changestate = false;
        playDefaultVideo();
        self.isProcessAudio = false;
        self.newMessageReceived = false;
        self.wakeupFlag = true;
        self.disabled = false;
        if (self.sendMode === 'audio') {
          setTimeout(() => {
            // 检查是否在十秒内有新的消息，如果没有则进入休眠状态
            if (!self.newMessageReceived) {
              sendSleepState();
            }
          }, 20000);
        }
      }
    });
  });
}
// const startRecording = () => {
//   // 初始化Recorder实例
//   state.recorder = new Recorder({
//     sampleBits: 16,                 // 采样位数，支持 8 或 16，默认是16
//     sampleRate: 16000,              // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，
//     numChannels: 1,                 // 声道，支持 1 或 2， 默认是1
//     compiling: true
//   });
//   // 获取录音设备,分析音频数据,检测是否有人说话
//   navigator.mediaDevices.getUserMedia({ audio: true })
//     .then(stream => {
//       const audioContext = new AudioContext();
//       const audioSource = audioContext.createMediaStreamSource(stream);

//       // 创建分析器节点
//       const analyzerNode = audioContext.createAnalyser();
//       analyzerNode.fftSize = 2048;

//       // 连接音频源到分析器节点
//       audioSource.connect(analyzerNode);

//       // 定义检测函数
//       const self = state;
//       let socketConnected = false; // WebSocket是否已连接
//       let intervalId; // 保存定时器的 ID
//       function detectSpeech() {
//         const bufferLength = analyzerNode.frequencyBinCount;
//         const dataArray = new Uint8Array(bufferLength);

//         analyzerNode.getByteFrequencyData(dataArray);

//         // 检查音频数据中是否有能量值大于阈值的部分
//         const threshold = 130; // 调整阈值以适应实际情况

//         for (let i = 0; i < bufferLength; i++) {
//           if (dataArray[i] > threshold) {
//             console.log("有人说话");
//             if (!socketConnected) {
//               connectSocketInit();
//               socketConnected = true;
//               //停止定时器
//               clearInterval(intervalId);
//             }
//             return;
//           }
//         }
//         console.log("没有人说话");
//       }
//       // setInterval(detectSpeech, 1000);
//       intervalId = setInterval(detectSpeech, 1000); //每秒执行一次检测函数
//     })
// }
function setItem() {
  const token = 'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjZiNjM5NWY2LTQxNTgtNDQ0Ny04Mjc0LTNiYTU3YTlkOTg4ZSJ9.TU-HXqAqyfK0AxH-fflQLdPOHUfbzr3kD3Ndnk8_WJMpt918Tetd6KIc4Bh3qkOMexZ729ESj9kypxDbGKk4Sg';
  localStorage.setItem('token', token);
}
// const getHotSpot = () => {
//   listQuestion().then(res => {
//     if (res.data.rows && res.data.rows.length != 0) {
//       let newData = res.data.rows.slice(0, 3);
//       newData.forEach(element => {
//         state.hotTopic.push({ question: element.question, answer: element.answer })
//       });
//       state.remenLength = true;
//     } else {
//       state.remenLength = false;
//     }
//   })
// }
// const menuClick = () => {
//   state.isMobile = !state.isMobile;
// }
// //反馈-好评
// const acclaim = () => {
//   let data = {
//     question: "好评",
//     answer: state.input,
//     type: "2",
//   }
//   //新增反馈
//   addRecord(data).then(() => {
//     //显示已收到反馈
//     state.messageShow = true;
//     state.btnShow = false;
//   })
// }
// //反馈-差评
// const negativeReviews = () => {
//   let data = {
//     question: "差评",
//     answer: this.input,
//     type: "2",
//   }
//   //新增反馈
//   addRecord(data).then(() => {
//     state.input = '';
//     //显示已收到反馈
//     state.messageShow = true;
//     state.btnShow = false;
//   })
// }
// 初始化滚动
const scrollDiv = ref(null);
async function initScrollBar() {
  await nextTick(); // 等待下次 DOM 更新
  scrollDiv.value.scrollTo({ top: scrollDiv.value.scrollHeight, behavior: 'smooth' });
  // state.$nextTick(() => {
  //   const scrollElem = scrollDiv;
  //   scrollElem.scrollTo({ top: scrollElem.scrollHeight, behavior: 'smooth' });
  // });
}
// 设置scroll的高度
function setScrollHeight(descHeight = 0) {
  // #ifdef MP-WEIXIN
  state.scrollHeight = `calc(100vh - 110rpx - ${descHeight}px)`;
  // #endif
  // #ifdef APP-PLUS
  state.scrollHeight = `calc(100vh - 110upx - ${descHeight}px)`;
  // #endif
  // #ifdef H5
  state.scrollHeight = `calc(100vh - 110upx - 290rpx - ${descHeight}px)`;
  // #endif
}
// 实时语音发送消息
function send() {
  pushMessage(state.content, 'text', () => {
    state.content = '';
  });
}
// 推送消息
function pushMessage(content, type = 'text', cb = () => { }) {
  // 组合消息体
  const msgData = {
    // userId: this.userId,
    type,
    content,
  };
  state.ask = msgData.content;
  // 加入信息
  state.list.push({
    source: state.userId,
    content: msgData.content,
    type: 'single',
    msgType: type,
  });
  // 初始化滚动条
  initScrollBar();
  cb ? cb() : state.togglePicker(0, 'file');

  // 显示加载中
  state.list.push({
    source: state.userId + 1,
    type: 'single',
    msgType: type,
    content: '',
    isThinking: true,
  });
  // 初始化滚动条
  initScrollBar();
  cb ? cb() : state.togglePicker(0, 'file');
}
// 输入框发送消息
function sendMessage() {
  state.sendMode = 'text';

  pushInputMessage(state.content, 'text', () => {
    state.content = '';
  });
}
function pushInputMessage(content, type = 'text', cb = () => { }) {
  // 组合消息体
  const msgData = {
    // userId: this.userId,
    type,
    content,
  };

  state.ask = msgData.content;
  // 加入信息
  state.list.push({
    source: state.userId,
    content: msgData.content,
    type: 'single',
    msgType: type,
  });

  // 初始化滚动条
  initScrollBar();
  cb ? cb() : state.togglePicker(0, 'file');
  // 显示加载中
  state.list.push({
    source: state.userId + 1,
    type: 'single',
    msgType: type,
    content: '',
    isThinking: true,
  });

  // 初始化滚动条
  initScrollBar();
  cb ? cb() : state.togglePicker(0, 'file');
  state.disabled = true;
  state.isProcessingAnswer = false;

  getAnswer(state.ask);
  // 初始化滚动条
  initScrollBar();
  cb ? cb() : state.togglePicker(0, 'file');
}
function checkMobile() {
  state.isMobile = window.innerWidth <= 768;
}
function playRandomVideo() {
  const randomIndex = Math.floor(Math.random() * state.videos.length);
  state.currentVideoIndex = randomIndex;
  state.flag = true; // 触发播放随机视频
  videoSrc();
  setTimeout(() => {
    state.videoKey = Math.random(10000); // 触发重新渲染
  }, 100);
}
function playDefaultVideo() {
  state.flag = false;
  // setTimeout(() => {
  //     this.defaultVideoKey = Math.random(10000); //触发重新渲染
  // },100);
}

const sleepStateText = computed(() => {
  return state.sleepState === 0 ? '休眠中' : '已唤醒';
});

// 监听器
watch(() => state.websocketStatus, (val) => {
  if (val) {
    connectSocketInit(); // 当开关打开时打开 WebSocket 连接
  }
  else {
    if (state.ws) {
      state.flag = false;
      sendStopFrame(); // 当开关关闭时关闭 WebSocket 连接
    }
  }
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', state.checkMobile);
  if (state.ws) {
    state.flag = false;
    sendStopFrameDes(); // 当开关关闭时关闭 WebSocket 连接
  }
});
</script>

<template>
  <PubPageMain class="box">
    <el-container>
      <el-main>
        <div class="right">
          <!-- 标题 -->
          <div class="right-text">
            绍兴电信大模型智能问答
            <div>
              <div :class="{ sleeping: state.sleepState === 0, awake: state.sleepState === 1 }">
                {{ sleepStateText }}
              </div>
            </div>
          </div>
          <!-- 问答 -->
          <div class="chat-container">
            <div ref="scrollDiv" class="scroll">
              <div class="item-space" />
              <div v-for="(item, index) in state.list" :key="index">
                <div class="item flex-row" :class="[item.source === state.userId ? 'right' : 'left']">
                  <!-- 用户 -->
                  <div v-if="item.source === state.userId" style="display: flex;">
                    <div class="content flex-row" @longpress="longPress(item)">
                      {{ item.content }}
                    </div>
                    <div class="face">
                      <!-- <img src="@/assets/img/user.png" /> -->
                      <img src="./components/img/user.png">
                    </div>
                  </div>
                  <!-- 回复 -->
                  <div v-else>
                    <div v-if="item.isThinking" class="loading-container">
                      <div class="loading-spinner" />
                      <div>请稍等，正在思考中...</div>
                    </div>
                    <div v-else style="display: flex;">
                      <div class="face">
                        <!-- <img src="@/assets/img/robot.jpg" /> -->
                        <img src="./components/img/robot.png">
                      </div>
                      <div class="content flex-row" @longpress="longPress(item)" v-html="item.content" />
                    </div>
                  </div>
                </div>
              </div>
              <div id="bottom" />
            </div>
            <!-- 输入 -->
            <div class="oper">
              <input
                v-model="state.content" :disabled="state.disabled" :focus="state.isFocus" :cursor-spacing="8"
                :adjust-position="false" type="text" class="input" placeholder="请输入您的问题" @keyup.enter="sendMessage"
              >
              <!-- <input :focus="isFocus" :cursor-spacing="8" @keyup.enter="send" :adjust-position="false"
              :class="{ 'recording': isRecording }" type="text" v-model="content" class="input" :placeholder="isRecording?'正在语音输入中...':'请输入您的问题'" :readonly="isRecording"/> -->
              <!-- 发送 -->
              <!-- <img :disabled="disabled" class="imgSend" @click="sendMessage" src="@/assets/img/send.png" /> -->
              <img :disabled="state.disabled" class="imgSend" src="./components/img/send.png" @click="sendMessage">
            </div>
          </div>
          <!-- 人物 -->
          <div class="figure">
            <!-- <video v-show="flag" :key="videoKey" autoplay loop muted class="status-video" ref="videoPlayer"> -->
            <video v-show="state.flag" :key="state.videoKey" autoplay loop muted class="status-video">
              <source :src="state.videoSrc">
            </video>
            <!-- <img v-show="!flag" src="@/assets/img/default.png" class="status-video" alt=""> -->
            <img v-show="!state.flag" src="./components/img/default.png" class="status-video" alt="">
          </div>
        </div>
      </el-main>
    </el-container>
  </PubPageMain>
</template>

<style scoped lang="scss">
.box {
  display: flex;
  flex-direction: column;
  max-width: 100%;
  max-height: 98%;
  // overflow: auto;
}

.sidebar {
  width: 20%;
  height: 100%;
}

.el-container {
  display: flex;
  height: 100vh;
  padding: 0;
  margin: 0;
}

.el-aside {
  position: relative;
  z-index: 999;
  float: left;
  width: 100%;
  height: 100%;
  background: #f1f2f3;
}

.message {
  display: inline-block;
  padding: 10px;
  margin-top: 10px;
  color: white;
  background: rgba(135, 206, 250, 0.5);
  border-radius: 5px;
}

.left {
  display: flex;
  flex-direction: column;

  // width: 85%;
  .left-first {
    margin-top: 100px;
    // margin-left: 20px;
  }

  .left-first-title {
    font-size: 18px;
    font-weight: bold;
  }

  .left-second {
    margin-top: 70px;
    // margin-left: 20px;
  }

  .input-title {
    margin-top: 15px;
    font-size: 12px;
    color: darkslategrey;
  }
}

.switch-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px;

  .switch-text {
    margin-left: 5px;
    font-size: 14px;
  }

  .switch-close {
    // padding: 10px;
    width: 15px;
    height: 15px;
  }
}

// .close {
//   margin-top: 10px;
//   margin-right: 10px;
//   text-align: end;

// }
.btn {
  display: flex;
  justify-content: space-between;
  width: 80%;
  margin-top: 10px;
}

.hotspot-font {
  display: -webkit-box;
  margin: 10px 0;
  overflow: hidden;
  text-overflow: ellipsis;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.right {
  display: flex;
  flex-direction: column;

  .right-text {
    display: flex;
    justify-content: center;
    //margin-top: 70px;
    font-size: 26px;
    font-weight: 600;
    text-align: center;
  }
}

/* stylelint-disable-next-line selector-pseudo-element-no-unknown */
::v-deep .el-textarea__inner {
  width: 250px;
  min-height: 14px;
  resize: none;
  border: none;
  border-radius: 5px;
}

/* stylelint-disable-next-line selector-pseudo-element-no-unknown */
::v-deep .el-button {
  padding: 5px 7px;
  color: dimgrey;
  background: #fff;
  border: 1px solid lightgrey;
  border-radius: 5px;
}

.sidebartransition {
  &-enter {
    transform: translateX(-100%); //整体划入之前隐藏在最左侧
  }

  &-enter-active {
    transition: all 0.5s ease; //划入过渡，用时0.5s
  }

  &-leave-to {
    transform: translateX(-120%); //整体划出之后隐藏在最左侧，之所以设置为-120%，见后文
  }

  &-leave-active {
    transition: all 0.5s ease; //划出过渡，用时0.5s
  }
}

.question-list {
  position: relative;
  z-index: 2;
  width: 80%;
  padding: 10rpx;
  background: #f5f3f1;
  border-radius: 10px;
}

.scroll {
  height: calc(-220px + 90vh);
  overflow-y: auto;
  transition: all 0.1s ease;
}

.item-space {
  height: 30px;
}

.time {
  margin-bottom: 20px;
  font-size: 24px;
  color: #666;
  text-align: center;
}

.cancel {
  width: 100%;
  height: 40px;
  margin-bottom: 30px;
  text-align: center;

  .text {
    font-size: 24px;
    color: #999;
  }
}

.hidden {
  animation-name: fadeOut;
  animation-duration: 2s;
  animation-fill-mode: forwards;
  /* 保持动画结束时的状态 */
}

@keyframes fadeOut {
  0% {
    opacity: 1;
  }

  100% {
    opacity: 0;
    // display: none; /* 在动画结束时隐藏div元素 */
  }
}

.show {
  animation-name: showOut;
  animation-duration: 2s;
  animation-fill-mode: forwards;
  /* 保持动画结束时的状态 */
}

@keyframes showOut {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}

.sendcss {
  position: absolute;
  left: 85%;
  display: flex;
  align-items: center;
  line-height: px;
}

.loading-container {
  display: flex;
  align-items: center;
}

.loading-spinner {
  width: 20px;
  height: 20px;
  margin-right: 10px;
  border: 3px solid #f3f3f3;
  border-top: 3px solid #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

@media only screen and (max-width: 768px) {
  .sidebar.collapsed {
    display: none;
    width: 100%;
  }

  .el-main {
    // background: #fff;
    // height: 100%;
    // width: 80%;
    position: absolute;
    top: 70px;
    right: 10px;
    left: 10px;
  }

  .closed {

    // width: 10%;
    img {
      width: 30px;
      height: 30px;
      padding: 10px 0 10px 10px;
    }

    .closed-title {
      position: relative;
      z-index: 99;
    }
  }

  .mousedown {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 50px;
    height: 50px;
    margin: 0 auto;
    margin-top: 10px;
    overflow: hidden;
    border-radius: 50%;

    .imgVoice {
      width: 80%;
      height: 80%;
      object-fit: cover;
    }
  }

  .oper {
    position: relative;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 35px;
    padding: 0 20px;
    margin-top: 10px;

    .input {
      width: 80%;
      height: 35px;
      padding: 0 20px;
      font-size: 14px;
      line-height: 35px;
      background: #f1f2f3;
      border: none;
      border-radius: 10px;
    }

    .input:focus {
      outline: 1px solid red;
    }

    .imgSend {
      position: absolute;
      right: 10%;
      width: 20px;
      height: 20px;
    }

    .btn {
      width: 90px;
      height: 52px;
      font-size: 24px;
      line-height: 52px;
      color: #fff;
      text-align: center;
      background-color: #2ba245;
      border-radius: 10px;
    }
  }

  .item {
    flex-direction: row;
    align-items: flex-start;
    justify-content: flex-start;
    margin-top: 10px;

    .face {
      width: 40px;
      height: 40px;

      img {
        width: 100%;
        height: 100%;
        object-fit: contain;
        border-radius: 50%;
      }
    }

    .content {
      // max-width: 300px;
      position: relative;
      flex: 1;
      padding: 15px;
      font-size: 16px;
      color: #000;
      word-break: break-all;
      word-wrap: break-word;
      background-color: #f1f2f3;
      border-radius: 10px;

      &::before {
        // border-bottom: 15px solid transparent;
        position: absolute;
        top: 0;
        width: 0;
        height: 0;
        content: "";
        // border-right: 15px solid transparent;
        border-top: 15px solid transparent;
      }

      .voice-icon {
        width: 32px;
        height: 40px;
        margin-right: 180px;
        margin-bottom: -8px;
      }
    }

    &.left {
      .face {
        margin-right: 10px;
      }

      .content::before {
        left: -8px;
        border-top: 15px solid transparent;
        border-left: 15px solid #f1f2f3;
        transform: rotate(180deg);
      }
    }

    &.right {
      flex-direction: row-reverse;

      .face {
        margin-left: 10px;
      }

      .content {
        background-color: #f1f2f3;

        &::before {
          right: -8px;
          border-right: 15px solid #f1f2f3;
          transform: rotate(180deg);
        }

        .voice-icon {
          margin-right: 0;
          margin-left: 180px;
          transform: rotate(180deg);
        }
      }
    }
  }

  .play {
    display: flex;
    align-items: center;
    margin-left: 5px;

    img {
      width: 20px;
      height: 20px;
    }
  }
}

@media only screen and (min-width: 1024px) {

  /* 在屏幕宽度大于等于 1024px 时应用的样式 */
  .oper {
    position: relative;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 35px;
    padding: 0 20px;
    margin-top: 10px;

    .input {
      width: 86%;
      height: 35px;
      padding: 0 20px;
      font-size: 14px;
      line-height: 35px;
      background: #f1f2f3;
      border: none;
      border-radius: 10px;
    }

    .input:focus {
      outline: 1px solid red;
    }

    .imgSend {
      position: absolute;
      right: 10%;
      width: 20px;
      height: 20px;
    }

    .btn {
      width: 90px;
      height: 52px;
      font-size: 24px;
      line-height: 52px;
      color: #fff;
      text-align: center;
      background-color: #2ba245;
      border-radius: 10px;
    }
  }

  .chat-container {
    margin: 0 150px;
  }

  .el-main {
    // background: #fff;
    // height: 100%;
    width: 80%;
    // margin-top: 70px;
  }

  .mousedown {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 50px;
    height: 50px;
    margin: 0 auto;
    margin-top: 10px;
    overflow: hidden;
    border-radius: 50%;

    .imgVoice {
      width: 80%;
      height: 80%;
      object-fit: cover;
    }
  }

  .closed {
    width: 20%;

    img {
      width: 30px;
      height: 30px;
      padding: 10px;
    }
  }

  .item {
    flex-direction: row;
    // margin: 0 30px 30px;
    align-items: flex-start;
    justify-content: flex-start;

    .face {
      width: 50px;
      height: 50px;

      img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        border-radius: 50%;
      }
    }

    .content {
      position: relative;
      max-width: 300px;
      padding: 20px 24px;
      font-size: 16px;
      color: #000;
      word-break: break-all;
      word-wrap: break-word;
      background-color: #f1f2f3;
      // min-height: 80px;
      border-radius: 10px;

      &::before {
        position: absolute;
        top: 0;
        width: 0;
        height: 0;
        content: "";
        border-top: 15px solid transparent;
      }

      .voice-icon {
        width: 32px;
        height: 40px;
        margin-right: 180px;
        margin-bottom: -8px;
      }
    }

    &.left {
      .face {
        margin-right: 10px;
      }

      .content::before {
        left: -7px;
        border-top: 15px solid transparent;
        border-left: 15px solid #f1f2f3;
        transform: rotate(180deg);
      }
    }

    &.right {
      flex-direction: row-reverse;

      .face {
        margin-left: 10px;
      }

      .content {
        background-color: #f1f2f3;

        &::before {
          right: -8px;
          border-right: 15px solid #f1f2f3;
          transform: rotate(180deg);
        }

        .voice-icon {
          margin-right: 0;
          margin-left: 180px;
          transform: rotate(180deg);
        }
      }
    }
  }

  .play {
    display: flex;
    align-items: center;
    margin-left: 10px;

    img {
      width: 30px;
      height: 30px;
    }
  }
}

/* stylelint-disable-next-line selector-pseudo-element-no-unknown */
::v-deep .el-dialog {
  margin-top: 75vh !important;
  margin-left: 20px;
}

/* stylelint-disable-next-line selector-pseudo-element-no-unknown */
::v-deep .el-dialog__headerbtn {
  display: none;
}

/* stylelint-disable-next-line selector-pseudo-element-no-unknown */
::v-deep .el-dialog__body > p {
  padding: 0;
  margin-top: 5px;
}

.sleeping {
  padding: 1px;
  margin-left: 3px;
  font-size: 12px;
  color: white;
  background: red;
  border-radius: 5px;
}

.awake {
  padding: 1px;
  margin-left: 3px;
  font-size: 12px;
  color: white;
  background: #2ba245;
  border-radius: 5px;
}

.figure {
  position: absolute;
  right: 0;
  bottom: 0;
  max-width: 150px;
  background-color: #fff;
  mix-blend-mode: screen;

  .status-video {
    max-width: 100%;
  }
}
</style>
